#pragma once
#ifndef __HWINCOMOBJECT_H__
#define __HWINCOMOBJECT_H__

#include "hwinobject.h"
#include "hwinobjimpl.h"
#include "hwinio.h"

namespace harlinn
{
    namespace windows
    {
        namespace io
        {
            class StreamBase;
        }

        class ComObject : public ComObjectBase
        {
            friend class Object;
            std::shared_ptr<Object> object;

            IUnknownImpl<ComObject,IUnknown> unknownImpl;
        public:
            typedef ComObjectBase Base;

            ComObject( std::shared_ptr<Object> theObject )
                : object(theObject),
                  unknownImpl(this)
            {

            }

            ~ComObject()
            {
                if(object)
                {
                    object->comObject = nullptr;    
                    object = nullptr;
                }
            }

            template <typename T>
            std::shared_ptr<T> InternalObject() const
            {
                return object->As<T>();
            }

        };


        



        class ComStream : public ComObject 
        {
            IStreamImpl<ComStream> streamImpl;
        public:
            typedef ComObject Base;

            ComStream( std::shared_ptr<harlinn::windows::io::StreamBase> streamBase )
                : Base(streamBase),
                  streamImpl(this)
            {

            }

            
            virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid,void ** ppvObject)
            {
                auto hr = InternalQueryInterface( riid,ppvObject);
                return hr;
            }

            virtual ULONG STDMETHODCALLTYPE AddRef( )
            {
                auto res = InternalAddRef( );
                return res;
            }

            virtual ULONG STDMETHODCALLTYPE Release( )
            {
                auto res = InternalRelease( );
                return res;
            }


            std::shared_ptr<harlinn::windows::io::StreamBase> GetStreamBase()
            {
                return InternalObject<harlinn::windows::io::StreamBase>();
            }


            HWIN_EXPORT HRESULT Read(void *pv,ULONG cb,ULONG *pcbRead);
            HWIN_EXPORT HRESULT Write(const void *pv,ULONG cb,ULONG *pcbWritten);
            HWIN_EXPORT HRESULT Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition);
            HWIN_EXPORT HRESULT SetSize(ULARGE_INTEGER libNewSize);
            HWIN_EXPORT HRESULT CopyTo( IStream *pstm,ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten);
            HWIN_EXPORT HRESULT Commit(DWORD grfCommitFlags);
            HWIN_EXPORT HRESULT Revert( void );
            HWIN_EXPORT HRESULT LockRegion( ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType);
            HWIN_EXPORT HRESULT UnlockRegion( ULARGE_INTEGER libOffset,ULARGE_INTEGER cb,DWORD dwLockType);
            HWIN_EXPORT HRESULT Stat( STATSTG *pstatstg,DWORD grfStatFlag );
            HWIN_EXPORT HRESULT Clone( IStream **ppstm );



        };


    };
};

#endif // __HWINCOMOBJECT_H__